package cn.kgc.controller;

import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RReadWriteLock;
import org.redisson.api.RSemaphore;
import org.redisson.api.RedissonClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

/**
 * @author YC
 */
@RestController
@RequestMapping("/redisson")
@Api(tags = "redisson测试接口")
@Slf4j
public class RedissonController {

    @Resource
    private RedissonClient redissonClient;

    @GetMapping("/readValue")
    public String readValue() {
        // 创建读写锁实例
        RReadWriteLock readWriteLock = redissonClient.getReadWriteLock("r-w-lock");
        // 创建写锁
        RLock readLock = readWriteLock.readLock();
        // 请求写锁
        readLock.lock();
        log.info("{}获得了读锁", Thread.currentThread().getName());
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
            log.debug("{}释放了读锁", Thread.currentThread().getName());
            readLock.unlock();
        }
        return "read success";
    }

    @GetMapping("/writeValue")
    public String writeValue1() {
        // 创建读写锁实例
        RReadWriteLock readWriteLock = redissonClient.getReadWriteLock("r-w-lock");
        // 创建写锁
        RLock writeLock = readWriteLock.writeLock();
        // 请求写锁
        writeLock.lock();
        log.info("{}获得了写锁", Thread.currentThread().getName());
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
            log.debug("{}释放了写锁", Thread.currentThread().getName());
            writeLock.unlock();
        }
        return "write success";
    }

    @GetMapping("/jia")
    public String jiaSemaphore() {
        // 获得名字叫做s1的信号量
        RSemaphore s1 = redissonClient.getSemaphore("s1");
        // 设置信号量中令牌初始数量10（只会在第一次访问时执行）
        s1.trySetPermits(10);
        // s1信号量+1
        s1.release();
        // 获得s1信号量的数量
        return String.valueOf(s1.availablePermits());
    }

    @GetMapping("/jian")
    public String jianSemaphore() {
        // 获得名字叫做s1的信号量
        RSemaphore s1 = redissonClient.getSemaphore("s1");
//        // 从信号量中获得令牌，如果有令牌继续程序执行，否则一直等待知道信号量中有令牌才继续执行程序
//        try {
//            s1.acquire();
//        } catch (InterruptedException e) {
//            throw new RuntimeException(e);
//        }
        // 尝试从信号量中获得令牌，如果有令牌返回true，否则返回false，无论返回值都继续执行程序
        if (s1.tryAcquire()) {
            log.debug("获得令牌");
        } else {
            log.debug("没有获得令牌");
        }
        return String.valueOf(s1.availablePermits());
    }

    @GetMapping("/hello")
    public String hello() {
        // 创建分布式锁
        RLock rLock = redissonClient.getLock("myLock");
        // 当前请求获得分布式锁
        // lock方法 若不指定时间默认上锁时间是30s，30s内未手动解锁会自动续时间（看门狗）。若指定时间后超过时间会自动解锁
        // 在开发中，如果指定时间，锁中的业务一定要在指定时间执行完毕（不建议），推荐不指定时间，但不要忘记手动unlock解锁
        rLock.lock();
        log.debug("{}获得了myLock锁", Thread.currentThread().getName());
        // 请求等待5s以后才释放分布式锁
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
            log.debug("{}释放了myLock锁", Thread.currentThread().getName());
            rLock.unlock();
        }
        // 返回逻辑字符串
        return "hello";
    }

}
